/* This file is part of the Crimsoon project
  * Copyright (C) 2009 Eduardo Henrique <eduardohleite@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public License
  * along with this library; see the file COPYING.LIB.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
*/

#include <QMenuBar>
#include <QMenu>
#include <QLabel>
#include <QStatusBar>
#include <QWidget>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QSplitter>
#include <QListWidget>
#include <QMessageBox>
#include <QTextStream>

#include <QModelIndex>
#include <QFileDialog>

#include <QtDebug>

#include "mainwindow.h"
#include "importmediadialog.h"
#include "gallerytree.h"
#include "gallerylist.h"
#include "playpanel.h"
#include "infopanel.h"
#include "playlist.h"
#include "track.h"
#include "gallery.h"

void MainWindow::createWidgets()
{
    createMenus();
    createStatusBar();
    createCentralWidget();
}

void MainWindow::createMenus()
{
    createActions();
    createFileMenu();
    createExecuteMenu();
    createToolsMenu();
    createHelpMenu();
}

void MainWindow::createFileMenu()
{
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(fileOpenFileAction);
    fileMenu->addAction(fileOpenDirectoryAction);
    //fileMenu->addAction(fileOpenUrlAction);
    //fileMenu->addSeparator();
    //fileMenu->addAction(fileSaveAsAction);
    //fileMenu->addAction(filePropertiesAction);
    fileMenu->addSeparator();
    fileMenu->addAction(fileExitAction);
}

void MainWindow::createExecuteMenu()
{
    executeMenu = menuBar()->addMenu(tr("&Execute"));    
    executeMenu->addAction(executeRepeatAction);
    executeMenu->addAction(executeRepeatAllAction);
}

void MainWindow::createToolsMenu()
{
    toolsMenu = menuBar()->addMenu(tr("&Tools"));
    toolsMenu->addAction(toolsImportMediaAction);
    toolsMenu->addAction(toolsUpdateGalleryAction);
}

void MainWindow::createHelpMenu()
{
    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(helpAboutAction);
}

void MainWindow::createActions()
{
    createFileMenuActions();
    createExecuteMenuActions();
    createToolsMenuActions();
    createHelpMenuActions();
}

void MainWindow::createFileMenuActions()
{
    fileOpenFileAction = new QAction(tr("Open &file..."), this);
    fileOpenFileAction->setStatusTip(tr("Play a music file."));
    connect(fileOpenFileAction, SIGNAL(triggered()), this, SLOT(onFileOpenFileTriggered()));

    fileOpenDirectoryAction = new QAction(tr("Open &directory..."), this);
    fileOpenDirectoryAction->setStatusTip(tr("Play music files in a directory."));
    connect(fileOpenDirectoryAction, SIGNAL(triggered()), this, SLOT(onFileOpenDirectoryTriggered()));

    /*fileOpenUrlAction = new QAction(tr("Open &URL..."), this);
    fileOpenUrlAction->setStatusTip(tr("Play a streaming URL."));
    connect(fileOpenUrlAction, SIGNAL(triggered()), this, SLOT(onFileOpenUrlTriggered()));

    fileSaveAsAction = new QAction(tr("&Save as..."), this);
    fileSaveAsAction->setStatusTip(tr("Save current file."));
    connect(fileSaveAsAction, SIGNAL(triggered()), this, SLOT(onFileSaveAsTriggered()));

    filePropertiesAction = new QAction(tr("&Properties..."), this);
    filePropertiesAction->setStatusTip(tr("View current file properties."));
    connect(filePropertiesAction, SIGNAL(triggered()), this, SLOT(onFilePropertiesTriggered()));*/

    fileExitAction = new QAction(tr("&Exit"), this);
    fileExitAction->setStatusTip(tr("Ends Crimsoon."));
    connect(fileExitAction, SIGNAL(triggered()), this, SLOT(onFileExitTriggered()));
}

void MainWindow::createExecuteMenuActions()
{
    executeRepeatAction = new QAction(tr("Repeat"), this);
    executeRepeatAction->setStatusTip(tr("Repeat the current song."));
    executeRepeatAction->setCheckable(true);
    connect(executeRepeatAction, SIGNAL(triggered()), this, SLOT(onExecuteRepeatTriggered()));

    executeRepeatAllAction = new QAction(tr("Repeat all"), this);
    executeRepeatAllAction->setStatusTip(tr("Repeat the current play list."));
    executeRepeatAllAction->setCheckable(true);
    connect(executeRepeatAllAction, SIGNAL(triggered()), this, SLOT(onExecuteRepeatAllTriggered()));
}

void MainWindow::createToolsMenuActions()
{
    toolsImportMediaAction = new QAction(tr("&Import media..."), this);
    toolsImportMediaAction->setStatusTip(tr("Imports media from selected directory to the gallery."));
    connect(toolsImportMediaAction, SIGNAL(triggered()), this, SLOT(onToolsImportMediaTriggered()));

    toolsUpdateGalleryAction = new QAction(tr("&Update gallery"), this);
    toolsUpdateGalleryAction->setStatusTip(tr("Updates the gallery."));
    connect(toolsUpdateGalleryAction, SIGNAL(triggered()), this, SLOT(onToolsUpdateGalleryTriggered()));
}

void MainWindow::createHelpMenuActions()
{
    helpAboutAction = new QAction(tr("&About..."), this);
    helpAboutAction->setStatusTip(tr("About Crimsoon."));
    connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(onHelpAboutTriggered()));
}

void MainWindow::createStatusBar()
{
    notifyLabel = new QLabel;
    statusBar()->addWidget(notifyLabel);
}

void MainWindow::createCentralWidget()
{
    centralWidget = new QWidget;    
    mainLayout    = new QHBoxLayout;
    overallLayout = new QVBoxLayout;
    splitter      = new QSplitter;

    playPanel     = new PlayPanel;
    infoPanel     = new InfoPanel;
    galleryList   = new GalleryList;
    galleryTree   = new GalleryTree;

    connect(galleryTree, SIGNAL(clicked(QModelIndex)), this, SLOT(onTreeClicked(QModelIndex)));
    connect(galleryList, SIGNAL(clicked(QModelIndex)), this, SLOT(onListClicked(QModelIndex))); // what if selected by keyboard?
    connect(galleryList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onListDoubleClicked(QModelIndex)));
    connect(playPanel, SIGNAL(playFileChanged(QString)), this, SLOT(onPlayFileChanged(QString)));
    connect(playPanel, SIGNAL(statusChanged()), this, SLOT(onPlayPanelStatusChanged()));

    splitter->addWidget(galleryTree);    

    splitter->addWidget(galleryList);    
    mainLayout->addWidget(splitter);
    mainLayout->addWidget(infoPanel);

    overallLayout->addLayout(mainLayout);
    overallLayout->addWidget(playPanel);

    centralWidget->setLayout(overallLayout);
    setCentralWidget(centralWidget);
}

void MainWindow::setPlayList()
{
    *playList = galleryList->getPlayList();
}

void MainWindow::onFileOpenFileTriggered()
{
    QStringList files = QFileDialog::getOpenFileNames(this, tr("Play File"), tr(""), "Music Files (*.mp3)");

    if (!files.isEmpty())
    {
        playPanel->forceStop();
        playList->clear();
        Gallery gallery;
        foreach (QString filename, files)
        {
            Track track;
            MusicFile file = gallery.getMusicFileInfo(filename);
            track.setAlbum(file.album);
            track.setArtist(file.artist);
            track.setFileName(filename);
            track.setLength(file.length);
            track.setTitle(file.title);
            track.setTrack(file.track);
            playList->append(track);
        }

        playPanel->prepare(playList, 0, true);
        galleryList->refresh(playList);
    }
}

void MainWindow::onFileOpenDirectoryTriggered()
{
}

void MainWindow::onFileOpenUrlTriggered()
{
}

void MainWindow::onFileSaveAsTriggered()
{
}

void MainWindow::onFilePropertiesTriggered()
{
}

void MainWindow::onFileExitTriggered()
{
    close();
}

void MainWindow::onExecuteRepeatTriggered()
{
    if (executeRepeatAction->isChecked())
    {
        if (executeRepeatAllAction->isChecked())
        {
            executeRepeatAllAction->setChecked(false);
        }

        playPanel->setRepeat();
    }
    else
    {
        playPanel->removeRepeat();
    }
}

void MainWindow::onExecuteRepeatAllTriggered()
{
    if (executeRepeatAllAction->isChecked())
    {
        if (executeRepeatAction->isChecked())
        {
            executeRepeatAction->setChecked(false);
        }

        playPanel->setRepeatAll();
    }
    else
    {
        playPanel->removeRepeatAll();
    }
}

void MainWindow::onToolsImportMediaTriggered()
{
    ImportMediaDialog dialog(this);
    if (dialog.exec() == QDialog::Accepted)
    {
        galleryTree->refreshGallery();
    }
}

void MainWindow::onToolsUpdateGalleryTriggered()
{
}

void MainWindow::onHelpAboutTriggered()
{
}

void MainWindow::onTreeClicked(QModelIndex index)
{
    if (galleryTree->isPlayingNowItem(index))
    {
        displaying = DisplayPlayingList;
        galleryList->refresh(playList);
        if (playList->count() > 0)
        {
            onPlayFileChanged(playPanel->currentFile());
        }

        return;
    }

    if (galleryTree->isMusicIndexItem(index))
    {
        displaying = DisplayGallery;
        return galleryList->refresh();
    }

    if (galleryTree->isArtistItem(index))
    {
        return galleryList->refresh(index.data().toString());
    }

    if (galleryTree->isAlbumItem(index))
    {
        return galleryList->refresh(index.parent().data().toString(), index.data().toString());
    }
}

void MainWindow::onListClicked(QModelIndex index)
{
    qint32 row = index.row();
    galleryList->selectRow(row);
    infoPanel->refresh(galleryList->getPathAt(row));

    if (playList->isEmpty())
    {
        setPlayList();
        playPanel->prepare(playList, row);
    }
}

void MainWindow::onListDoubleClicked(QModelIndex index)
{
    qint32 row = index.row();
    galleryList->selectRow(row);
    infoPanel->refresh(galleryList->getPathAt(row));
    setPlayList();
    playPanel->prepare(playList, row, true);
}

void MainWindow::onPlayFileChanged(QString filename)
{
    currentFilename = filename;
    onPlayPanelStatusChanged();
    qint32 index = galleryList->isShowingPath(filename);
    if (index > -1)
    {
        galleryList->selectRow(index);
        infoPanel->refresh(filename);
    }
}

void MainWindow::onPlayPanelStatusChanged()
{
    QString message;
    QTextStream out(&message);

    switch (playPanel->getStatus())
    {
        case PLAYPANEL_PLAYING:
            out << "Now playing: " << currentFilename << ".";
            break;
        case PLAYPANEL_PAUSED:
            out << "Paused.";
            break;
        case PLAYPANEL_STOPPED:
            out << "Stopped.";
            break;
        case PLAYPANEL_ERROR:
            out << "Error.";
            break;
        case PLAYPANEL_READY:
            out << "Ready.";
    }

    notifyLabel->setText(message);
}

void MainWindow::destroyWidgets()
{
    delete fileMenu;
    delete executeMenu;
    delete toolsMenu;
    delete helpMenu;
    delete fileOpenFileAction;
    delete fileOpenDirectoryAction;
    //delete fileOpenUrlAction;
    //delete fileSaveAsAction;
    //delete filePropertiesAction;
    delete fileExitAction;
    delete executeRepeatAction;
    delete toolsImportMediaAction;
    delete toolsUpdateGalleryAction;
    delete helpAboutAction;
    delete notifyLabel;
    delete centralWidget;
    delete mainLayout;
    delete splitter;
    delete galleryList;
    delete galleryTree;
    delete playPanel;
    delete overallLayout;
    delete playList;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    createWidgets();

    playList = new PlayList;
    displaying = DisplayPlayingList;

    setPlayList();
}

MainWindow::~MainWindow()
{    
    destroyWidgets();
}
